/**
 * Esta classe realiza o gerenciamento dos buscadores dos preditores
 */
package epibot.testeProteinas;

import epibot.BancoDeDados.ArmazenaDados.Fasta;
import epibot.EstruturasBiologicas.Epitopo;
import epibot.EstruturasBiologicas.Proteina;
import epibot.WebRobots.Bimas;
import epibot.WebRobots.IEDB_consensus;
import epibot.WebRobots.NETMHC;
import epibot.WebRobots.SVMHC;
import epibot.WebRobots.SYFPEITHI;
import java.io.IOException;
import java.util.ArrayList;
import javax.swing.SwingUtilities;

/**
 *
 * @author Rafael Tosta
 */
public class GerenciadorRobot_Teste extends Thread {

    /**
     * Tamanho dos epitopos
     */
    private String tamanho;
    /**
     * Alelo
     */
    private String alelo;
    /**
     * Lista dos motores de buscas que serão utilizados
     */
    private ArrayList<String> motores;
    /**
     * Lista de proteinas a ser consultado
     */
    private ArrayList<Fasta> listaProteinas;
    /**
     * Referência para o painel de busca
     */
    private JPanelBuscaRobot p;
    /**
     * Referência da barra de progresso
     */
    /**
     * Referência para o campo de avisos
     */
    private ArrayList<String[]> l_calibradores;
    private ArrayList<Proteina> listaBimas = new ArrayList<Proteina>();
    private ArrayList<Proteina> listaNETMHC = new ArrayList<Proteina>();
    private ArrayList<Proteina> listaIEDB_consensus = new ArrayList<Proteina>();
    private ArrayList<Proteina> listaSYFPEITHI = new ArrayList<Proteina>();
    private String nomeCalibragem;

    /**
     * Construtor
     *
     * @param jTextAreaAvisos
     */
    public GerenciadorRobot_Teste() {
    }

    /**
     * Define os parametros necessarios antes da realização das buscas nos sites
     * e o disparo da thread
     *
     * @param motores Motores de busca
     * @param listaDeProteinas Lista de proteínas a ser consultado
     * @param conexaoSQLite Conexão com o banco de dados
     * @param p eferência para o painel de busca
     * @param b Referência da barra de progresso
     * @param tamanho Tamanho do epitopo
     * @param alelo Alelo
     */
    public void set(ArrayList<Fasta> listaDeProteinas, ArrayList<String> motores,
            JPanelBuscaRobot p, String tamanho,
            String alelo, String nomeCalibragem) {
        this.tamanho = tamanho;
        this.alelo = alelo;
        this.listaProteinas = listaDeProteinas;
        this.p = p;
        this.nomeCalibragem = nomeCalibragem;
        this.motores = motores;

    }

    public void print(final String t) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                p.setjTextArea(t);
            }
        });
    }

    public void iniciaPBar(final int max) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                p.iniciaPBar(max);
            }
        });

    }

    public void setValuePBar(final int v) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                p.setValuePBar(v);
            }
        });

    }

    /**
     * Roda os motores de busca em uma thead para poder deixar a interface
     * gráfica sem travar e para a barra de progresso
     *
     * Apatir da lista de motores de busca é definido em quais sites será
     * utilizado na consulta
     */
    @Override
    public void run() {

        print("Consulting...\n");
        iniciaPBar(listaProteinas.size());
        for (int i = 0; i < listaProteinas.size(); i++) {
            Fasta proteina = listaProteinas.get(i);
            print("Protein: " + proteina.getInformacao());

            for (int j = 0; j < motores.size(); j++) {

                if (motores.get(j).equals("Bimas")) {
                    //obtem aproteina pelo webRobot
                    Proteina p = executaBimas(proteina);

                    if (p != null) {
                        listaBimas.add(p);
                    }
                }
                if (motores.get(j).equals("NETMHC")) {
                    //obtem aproteina pelo webRobot
                    Proteina p = executaNETMHC(proteina);

                    if (p != null) {
                        listaNETMHC.add(p);
                    }
                }
                if (motores.get(j).equals("IEDB_consensus")) {
                    //obtem aproteina pelo webRobot
                    Proteina p = executaIEDB_consensus(proteina);

                    if (p != null) {
                        listaIEDB_consensus.add(p);
                    }
                }
                if (motores.get(j).equals("SYFPEITHI")) {
                    //obtem aproteina pelo webRobot
                    Proteina p = executaSYFPEITHI(proteina);

                    if (p != null) {
                        listaSYFPEITHI.add(p);
                    }
                }
            }
            setValuePBar(i + 1);
        }

        print("\nConsolidation started... ");
        //consolida os resultados        
        Consolidacao g = new Consolidacao(this, nomeCalibragem, tamanho, alelo, juntaConsultas());
        g.iniciaConsolidacao();

    }

    public void telainicial() {
        p.telainicial();
    }

    //coloca todas as consultas em um unico array (consulta)
    private ArrayList<ArrayList<Proteina>> juntaConsultas() {
        ArrayList<ArrayList<Proteina>> consulta = new ArrayList<ArrayList<Proteina>>();

        for (int i = 0; i < motores.size(); i++) {
            if (motores.get(i).equals("Bimas")) {
                consulta.add(listaBimas);
            }
            if (motores.get(i).equals("NETMHC")) {
                consulta.add(listaNETMHC);
            }
            if (motores.get(i).equals("IEDB_consensus")) {
                consulta.add(listaIEDB_consensus);
            }
            if (motores.get(i).equals("SYFPEITHI")) {
                consulta.add(listaSYFPEITHI);
            }
        }
        return consulta;
    }

    private Proteina executaBimas(Fasta p1) {
        Proteina prot = null;
        try {
            prot = Bimas.processCalibragem(p1.getSequencia(), alelo, tamanho, p1.getCodProteina(), "Bimas");
            if (prot != null) {
                prot.setCabecalho(p1.getInformacao());
            }

        } catch (IOException ex) {
            //jTextAreaAvisos.append("\nError in consultation Bimas.);
        }
        return prot;
    }

    private Proteina executaNETMHC(Fasta p1) {
        Proteina prot = null;
        try {

            prot = NETMHC.processCalibragem(p1.getSequencia(), alelo, tamanho, p1.getCodProteina(), "NETMHC");
            if (prot != null) {
                prot.setCabecalho(p1.getInformacao());
            }

        } catch (IOException ex) {
            //jTextAreaAvisos.append("\nError in consultation NETMHC!\n" + ex.getMessage() + "\n");
        }
        return prot;
    }

    private Proteina executaIEDB_consensus(Fasta p1) {
        Proteina prot = null;

        try {
            prot = IEDB_consensus.processCalibragem(p1.getSequencia(), alelo, tamanho, p1.getCodProteina(), "IEDB_consensus");
            if (prot != null) {
                prot.setCabecalho(p1.getInformacao());
            }
        } catch (IOException ex) {
            //jTextAreaAvisos.append("\nError in consultation IEDB_consensus!\n" + ex.getMessage() + "\n");
        }

        return prot;
    }

    private Proteina executaSYFPEITHI(Fasta p3) {
        Proteina prot = null;

        String r = p3.getSequencia().replace("\n", "");
        r = r.replace(" ", "");
        int N = r.length();
        int D = 2047;

        int n_pedacos = (int) Math.ceil(N / 2048.0);
        // System.out.println(N + " , " + n_pedacos);

        try {
            int inicio = 0;
            int fim = 0;
            if (N <= 2048) {
                fim = N - 1;
            } else {
                fim = D;
            }
            for (int k = 0; k < n_pedacos; k++) {

                //System.out.println(inicio + " - " + fim);
                String R = r.substring(inicio, fim);

                prot = SYFPEITHI.processCalibragem(R, alelo, tamanho, p3.getCodProteina(), "SYFPEITHI");

                if (prot != null) {
                    prot.setCabecalho(p3.getInformacao());
                }
                inicio = fim;

                if (N >= (D * (k + 2))) {
                    fim = D * (k + 2);
                } else {
                    fim = N - 1;
                }

            }
        } catch (IOException ex) {

        }
        return prot;
    }
}
